/*
	The Raja Toolkit.
	Copyright (C) 2011 Raja-Toolkit Foundation

	This library is free software; you can redistribute it and/or
	modify it under the terms of the GNU Lesser General Public
	License as published by the Free Software Foundation; either
	version 3.0 of the License, or (at your option) any later version.

	This library is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
	Lesser General Public License for more details.

	You should have received a copy of the GNU Lesser General Public
	License along with this library; if not, write to the Free Software
	Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
*/

#ifndef RAJA_RENDER_DRIVER_HPP
#define RAJA_RENDER_DRIVER_HPP

#include "../types.hpp"
#include "../math/math.hpp"

#include "sampler2.hpp"

namespace raja
{
namespace  render
{
struct	sampler_format;

struct	resource;
struct	uniform;
struct	sampler;
struct	sampler2;
struct	sampler3;
struct	buffer;
struct	vertex_buffer;
struct	index_buffer;
struct	render_buffer;
struct	frame_buffer;
struct	program;
struct	material;
struct	vertex_attrib;
struct	draw_call;
class	device;

typedef boost::shared_ptr<device>	device_ptr;

class device
{
	// start with forward declaration of internal structures/class
protected:
	struct	internal_sampler;
	typedef	boost::shared_ptr<internal_sampler>		internal_sampler_ptr;

	struct	internal_sampler2;
	typedef	boost::shared_ptr<internal_sampler2>	internal_sampler2_ptr;

public:



	friend struct	resource;
	friend struct	uniform;
	friend struct	sampler;
	friend struct	sampler2;
	friend struct	sampler3;
	friend struct	buffer;
	friend struct	vertex_buffer;
	friend struct	index_buffer;
	friend struct	render_buffer;
	friend struct	frame_buffer;
	friend struct	program;
	friend struct	material;
	friend struct	vertex_attrib;
	friend struct	draw_call;

	///////////////////////////////////////////////////////////////////
	/// @section driver public types
	///////////////////////////////////////////////////////////////////

	///////////////////////////////////////////////////////////////////
	/// render driver supported types
	///////////////////////////////////////////////////////////////////
	enum RD_TYPE
	{
		RDT_GLES_1_1,	///< opengl es 1.1
		RDT_GLES_2_0,	///< opengl es 2.0
		RDT_GL_14,		///< opengl 1.4
		RDT_GL_21,		///< opengl 2.1
		RDT_GL_33,		///< opengl 3.3
		RDT_GL_41,		///< opengl 4.1

	};

	///////////////////////////////////////////////////////////////////
	/// resource usage
	///////////////////////////////////////////////////////////////////
	enum RESOURCE_USAGE
	{
		RU_DEFAULT,	///< default usage
		RU_STATIC,	///< static usage (updated once per program run)
		RU_DYNAMIC,	///< dynamic usage (updated once per frame)
	};


	///////////////////////////////////////////////////////////////////
	/// @section device public methods
	///////////////////////////////////////////////////////////////////

	///
	/// create a device
	///
	static device_ptr		create_device(RD_TYPE t);

	///
	/// create a sampler2
	///
	virtual sampler2		create_sampler2(uint32 width, uint32 height, const sampler_format &fmt, RESOURCE_USAGE usage, void *data) = 0;

	/// destructor
	virtual					~device() {}

protected:
	device() {}

	/// @warning This is not a dummy object!!!
	///
	/// Driver implementations should extend this internally and never
	/// make it public.
	///
	/// This should contain driver dependent objects
	struct internal_sampler
	{
		virtual ~internal_sampler() {}
	};

	/// @warning This method should never be called directly
	virtual void			release_sampler(internal_sampler_ptr sampler_)	= 0;


	/// @warning This is not a dummy object!!!
	///
	/// Driver implementations should extend this internally and never
	/// make it public.
	///
	/// This should contain driver dependent objects
	struct internal_sampler2
	{
		virtual ~internal_sampler2() {}
	};

	/// @warning This method should never be called directly
	virtual void			release_sampler2(internal_sampler2_ptr sampler_)	= 0;


	/// sampler2 list
	boost::unordered_map<internal_sampler2_ptr, sampler2>	_sampler2_list;


};	// class device


}	// namespace render
}	// namespace raja

// device members should be declared afterward otherwise we get an incomplete forward declaration
#include "sampler2.hpp"

#endif // RAJA_RENDER_DRIVER_HPP
